using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using IFXplus.SmartStorage.Utils;

namespace IFXplus.SmartStorage
{
    [Serializable]
    public class StorageEntry : IXmlSerializable
    {
        #region Privates

        private string _Key = string.Empty;
        private DateTime _CreationTime = DateTime.MinValue;
        private DateTime _LastAccessTime = DateTime.MinValue;
        private TimeSpan _DefaultAbsoluteTTL = StorageItemMetadata.NoAbsoluteTTL;
        private object _Value = null;

        #endregion

        #region Constructors

        public StorageEntry() { }

        public StorageEntry(string key, DateTime creationtime, TimeSpan defaultabsolutettl, object value)
        {
            Key = key;
            CreationTime = creationtime;
            LastAccessTime = creationtime;
            DefaultAbsoluteTTL = defaultabsolutettl;
            Value = value;
        }

        #endregion

        #region Properties

        public string Key
        {
            get { return _Key; }
            set { _Key = value; }
        }

        public DateTime CreationTime
        {
            get { return _CreationTime; }
            set { _CreationTime = value; }
        }

        public DateTime LastAccessTime
        {
            get { return _LastAccessTime; }
            set { _LastAccessTime = value; }
        }

        public TimeSpan DefaultAbsoluteTTL
        {
            get { return _DefaultAbsoluteTTL; }
            set { _DefaultAbsoluteTTL = value; }
        }
        
        public object Value
        {
            get { return _Value; }
            set { _Value = value; }
        }

        #endregion

        #region Methods

        public bool IsExpired()
        {
            return IsExpired(DefaultAbsoluteTTL);
        }

        public bool IsExpired(TimeSpan ttl)
        {
            return (ttl != StorageItemMetadata.NoAbsoluteTTL && DateTime.Now > CreationTime.Add(ttl));
        }

        public override string ToString()
        {
            return string.Format("{{ \"Key\" : \"{0}\", \"CreationTime\" : {1}, \"Value\" : {{ {2} }} }}", Key, CreationTime, Value);
        }
        
        #endregion
        
        #region IXmlSerializable Members
        
        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement();
            reader.MoveToContent();
            if (reader.LocalName == "Key")
                Key = (reader.IsEmptyElement) ? string.Empty : reader.ReadElementString();
            if (reader.LocalName == "CreationTime")
                CreationTime = (reader.IsEmptyElement) ? DateTime.MinValue : reader.ReadElementContentAsDateTime();
            if (reader.LocalName == "LastAccessTime")
                LastAccessTime = (reader.IsEmptyElement) ? DateTime.MinValue : reader.ReadElementContentAsDateTime();
            if (reader.LocalName == "DefaultAbsoluteTTL")
                DefaultAbsoluteTTL = (reader.IsEmptyElement) ? StorageItemMetadata.NoAbsoluteTTL : XmlConvert.ToTimeSpan(reader.ReadElementString());
            if (reader.LocalName == "Value")
                Value = (reader.IsEmptyElement) ? null : Base64Serializer.Deserialize(reader.ReadElementString());            
            reader.MoveToContent();
            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {            
            writer.WriteElementString("Key", Key);
            writer.WriteElementString("CreationTime", XmlConvert.ToString(CreationTime, XmlDateTimeSerializationMode.Utc));
            writer.WriteElementString("LastAccessTime", XmlConvert.ToString(LastAccessTime, XmlDateTimeSerializationMode.Utc));
            writer.WriteElementString("DefaultAbsoluteTTL", XmlConvert.ToString(DefaultAbsoluteTTL));
            writer.WriteElementString("Value", Base64Serializer.Serialize(Value));
        }

        #endregion
    }
}
